#!/usr/bin/env python
# -*- coding:utf-8 -*-

# @author           = 'zhouyi'
# @mail             = '6098550@qq.com'
# @lastModifiedTime = 2017-02-28


BLOCK0_EN        = 0x01
BLOCK1_EN        = 0x02
BLOCK2_EN        = 0x04
NEEDSERIAL       = 0x08
EXTERNKEY        = 0x10
NEEDHALT         = 0x20

# reture value.
ERR_REQUEST      = 8
ERR_READSERIAL   = 9
ERR_SELECTCARD   = 10
ERR_LOADKEY      = 11
ERR_AUTHKEY      = 12
ERR_READ         = 13
ERR_WRITE        = 14
ERR_NONEDLL      = 21
ERR_DRIVERORDLL  = 22
ERR_DRIVENULL    = 23
ERR_TIMEOUT      = 24
ERR_TXSIZE       = 25
ERR_TXCRC        = 26
ERR_RXSIZE       = 27
ERR_RXCRC        = 28



import ctypes
import binascii

# RDFI wraper
class IC_Reader(object):
    # base property    
    __api = None


    def __init__(self):
        import os  
        import inspect  
        this_file = inspect.getfile(inspect.currentframe())  
        dirpath = os.path.abspath(os.path.dirname(this_file))        
        FileName = os.path.join(dirpath, "OUR_MIFARE.dll")
        print FileName
    # stdcall
        self.__api = ctypes.WinDLL(FileName)
    # cdecl        
        #self.__api = ctypes.CDLL(FileName)


    # beep x ms
    def beep(self):
        try:
            self.__api.pcdbeep(50)
        except Exception as err:
            print err


    # read the infomation of the ic card.
    def read(self):
        status       = ctypes.c_ubyte(0)
        area_no      = ctypes.c_ubyte(0)   # 0-15
        auth_mode    = ctypes.c_ubyte(1)   # >1 A or B password.
        ctrl_word    = ctypes.c_ubyte(BLOCK0_EN + BLOCK1_EN + BLOCK2_EN + EXTERNKEY)
        ArrayPiccKey    = ctypes.c_ubyte * 6
        ArrayPiccSerial = ctypes.c_ubyte * 4 
        ArrayPiccData   = ctypes.c_ubyte * 48
        picc_key     = ArrayPiccKey(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF)
        picc_serial  = ArrayPiccSerial()
        picc_data    = ArrayPiccData()
        
        status = self.__api.piccreadex(ctrl_word, picc_serial, area_no, auth_mode, picc_key, picc_data)
        self.__api.picchalt()
        if status == 0:
            self.beep()
            print '-------operation success!------------'
            print "area_no=%d, auth_mode=%d, ctrl_word=%d ret=%d" % (area_no.value, auth_mode.value, ctrl_word.value, status)
        
            # card_id = ''
            # for i in range(0, 4):
            #     card_id += hex(picc_serial[i])[2:].upper()
            # return card_id
            card_data =''
            #for i in range(0, 48):        	
            for i in range(0, 12):          
                card_data += hex(picc_data[i])[2:].upper()
            return card_data


        elif status == 8:
            print 'please put the card to the address!'
        elif status == 21:
            print 'no find the dll ICUSB.dll'
        else: 
            print 'exception!'
        
        return ''

        # card_id = ''
        # for i in range(0, 4):
        #     card_id += hex(picc_serial[i])[2:].upper()
        # print card_id
        
        # #print picc_data
        # card_data =''
        # for i in range(0, 48):        	
        # 	card_data += hex(picc_data[i])[2:].upper()
        # print card_data
  

    # write the infomation to the ic card.
    def write(self, data):
        try:
            status       = ctypes.c_ubyte(0)
            area_no      = ctypes.c_ubyte(8)
            auth_mode    = ctypes.c_ubyte(1)   #A or B password.
            ctrl_word    = ctypes.c_ubyte(BLOCK0_EN + BLOCK1_EN + BLOCK2_EN + EXTERNKEY)
            ArrayPiccKey    = ctypes.c_ubyte * 6
            ArrayPiccSerial = ctypes.c_ubyte * 4
            ArrayPiccData   = ctypes.c_ubyte * 48
            picc_key     = ArrayPiccKey(0xFF, 0xFF, 0xFF, 
            							0xFF, 0xFF, 0xFF)
            picc_serial  = ArrayPiccSerial()
            picc_data    = ArrayPiccData()
            # print status
            # print area_no
            # print auth_mode
            # print ctrl_word
            # print picc_key
            # print picc_key[0]
            # print picc_serial
            # print picc_serial[0]
            # print picc_data
            # print picc_data[0]
            # print self.FileName
            #ret = self.__api.piccwriteex(ctrl_word, picc_serial, area_no, auth_mode, picc_key, picc_data)
            print ret
            beep()
            #self.__api.piccreadex()
        except Exception as err:
            print err


def sendto_bg_service(iccard_id, service_url='http://mi.hakurei.cn/api/account/icLogin'):
    import urllib
    import urllib2    
    values = {'name':iccard_id}
    send_data = urllib.urlencode(values)
    print send_data
    request  = urllib2.Request(service_url, send_data)
    response = urllib2.urlopen(request, data=None, timeout=30)
    res_context = response.read()
    return res_context







import win32serviceutil   
import win32service   
import win32event   
  
class ICCardService(win32serviceutil.ServiceFramework):   
    """ 
    Usage: 'ICCardService.py [options] install|update|remove|start [...]|stop|restart [...]|debug [...]' 
    Options for 'install' and 'update' commands only: 
     --username domain\username : The Username the service is to run under 
     --password password : The password for the username 
     --startup [manual|auto|disabled|delayed] : How the service starts, default = manual 
     --interactive : Allow the service to interact with the desktop. 
     --perfmonini file: .ini file to use for registering performance monitor data 
     --perfmondll file: .dll file to use when querying the service for 
       performance data, default = perfmondata.dll 
    Options for 'start' and 'stop' commands only: 
     --wait seconds: Wait for the service to actually start or stop. 
                     If you specify --wait with the 'stop' option, the service 
                     and all dependent services will be stopped, each waiting 
                     the specified period. 
    """  
    #服务名  
    _svc_name_ = "ICCardService"  
    #服务显示名称  
    _svc_display_name_ = "ICCard Service"  
    #服务描述  
    _svc_description_ = "ICCard read service."  
  
    def __init__(self, args):   
        win32serviceutil.ServiceFramework.__init__(self, args)   
        self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)  
        self.logger = self._getLogger()  
        self.isAlive = True  
          
    def _getLogger(self):  
        import logging  
        import os  
        import inspect  
          
        logger = logging.getLogger('[ICCardService]')  
          
        this_file = inspect.getfile(inspect.currentframe())  
        dirpath = os.path.abspath(os.path.dirname(this_file))
        handler = logging.FileHandler(os.path.join(dirpath, "ICCardService.log"))  
          
        formatter = logging.Formatter('%(asctime)s %(name)-12s %(levelname)-8s %(message)s')  
        handler.setFormatter(formatter)  
          
        logger.addHandler(handler)  
        logger.setLevel(logging.INFO)  
          
        return logger  
  
    def SvcDoRun(self):
        try:
            self.logger.info("svc do run....")   

            reader = IC_Reader()
            
            import time              
            while self.isAlive:  
                #self.logger.error("I am alive.")
                iccard_id = ""

                try:
                    iccard_id = reader.read()                    
                except Exception as err:
                    self.logger.error("read card error:%s" % (err))
                
                if iccard_id != '':
                    try:
                        self.logger.info(iccard_id)
                        res_context = sendto_bg_service(iccard_id)
                        self.logger.info(res_context)
                    except Exception as err:
                        self.logger.error("net error:%s" % (err))

                time.sleep(2)  

        except Exception as err:
            self.logger.error(err)   
        # 等待服务被停止   
        #win32event.WaitForSingleObject(self.hWaitStop, win32event.INFINITE)   
              
    def SvcStop(self):   
        # 先告诉SCM停止这个过程   
        self.logger.error("svc do stop....")  
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)   
        # 设置事件   
        win32event.SetEvent(self.hWaitStop)   
        self.isAlive = False  
  
if __name__=='__main__':   
    win32serviceutil.HandleCommandLine(ICCardService) 